package com.nx.platform.es.biz.query.count.handler;


import com.google.common.collect.LinkedListMultimap;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Table;
import com.nx.platform.es.bean.modle.query.QueryField;
import com.nx.platform.es.biz.query.count.CountRequestContext;
import com.nx.platform.es.biz.wrapper.parser.StatementOperator;
import org.apache.commons.collections4.CollectionUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;

import java.util.List;
import java.util.Map.Entry;

import static com.nx.platform.es.biz.wrapper.parser.StatementOperator.EQUAL;
import static com.nx.platform.es.biz.wrapper.parser.StatementOperator.NOT_EQUAL;


/**
 * @author
 * @since 2016年10月15日
 */
public enum CountQueryHandler implements CountRequestHandler {

    INSTANCE;

    @Override
    public void handle(CountRequestContext context) {

        // Query
        QueryBuilder queryBuilder = null;

        // 过滤查询拼接
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        Table<String, StatementOperator, List<String>> queryTable = context.getQueryTable();
        List<QueryField> queryFields = context.getQueryFields();
        for (QueryField queryField : queryFields) {
            ListMultimap<Boolean, QueryBuilder> queryBuilders = LinkedListMultimap.create();
            // 正向条件
            List<String> positives = queryTable.get(queryField.getFace(), EQUAL);
            if (CollectionUtils.isNotEmpty(positives)) {
                for (String positive : positives) {
                    queryField.handle(context, EQUAL, positive, queryBuilders);
                }
            } else {
                queryField.handle(context, EQUAL, null, queryBuilders);
            }
            // 逆向条件
            List<String> negatives = queryTable.get(queryField.getFace(), NOT_EQUAL);
            if (CollectionUtils.isNotEmpty(negatives)) {
                for (String negative : negatives) {
                    queryField.handle(context, NOT_EQUAL, negative, queryBuilders);
                }
            }
            //
            for (Entry<Boolean, QueryBuilder> entry : queryBuilders.entries()) {
                if (Boolean.TRUE.equals(entry.getKey())) {
                    switch (queryField.getType()) {
                    case StringMatch:
                    case StringMultiMatch:
                        boolQueryBuilder.must(entry.getValue());
                        break;
                    default:
                        boolQueryBuilder.filter(entry.getValue());
                        break;
                    }
                } else {
                    boolQueryBuilder.mustNot(entry.getValue());
                }
            }
        }

        // 检查过滤查询
        if (boolQueryBuilder.hasClauses()) {
            queryBuilder = boolQueryBuilder;
        }

        // Query为空，默认查询所有数据
        if (queryBuilder == null) {
            queryBuilder = QueryBuilders.matchAllQuery();
        }

        if (context.isUseRequestCache()) {
            context.getRequest().requestCache(true);
        }

        context.getRequest().source().timeout(context.getTimeout()).query(queryBuilder);
    }

}
